/*
 * test_shm.cpp
 *
 *  Created on: Mar 30, 2014
 *      Author: killerg
 */

#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "share/clock.h"
#include "share/patterns.h"
#include "share/util.h"

using namespace std;

static const int CACHED_NUM = 20000;

struct playerdata_t {
	int id = -1;
	char name[40];
	int att[100];
};

struct mapdata_t {
	int magic_head;
	playerdata_t players[CACHED_NUM];
	int magic_tail;
};

struct mapdatamgr_t {
	mapdata_t* mapdata;
	list<playerdata_t*> free_datas;
	ptr_map<int, playerdata_t*> datas;

	bool init() {
		//int fd = open("hello", O_RDWR | O_CREAT, S_IRWXU);
		mapdata = (mapdata_t*)shm_new("/hello", sizeof(*mapdata));
		if (NULL == mapdata)
			return false;

		if (mapdata->magic_head == 0x1234 && mapdata->magic_tail == 0x5678) {
			for (int i=0; i<CACHED_NUM; ++i) {
				playerdata_t* data = mapdata->players + i;
				if (data->id >= 0) {
					assert(datas.count(data->id) == 0);
					datas.set(data->id, data);
				} else {
					free_datas.push_back(data);
				}
			}
		} else {
			memset(mapdata, -1, sizeof(*mapdata));
			mapdata->magic_head = 0x1234;
			mapdata->magic_tail = 0x5678;
			for (int i=0; i<CACHED_NUM; ++i)
				free_datas.push_back(mapdata->players + i);
		}


		return true;
	}
	void destroy() {
		shm_free("/hello", sizeof(*mapdata), mapdata);
	}

	playerdata_t* fetch(int id) {
		playerdata_t* data = datas.get(id);
		if (NULL != data)
			return data;

		if (free_datas.empty())
			return NULL;

		data = free_datas.front();
		free_datas.pop_front();
		data->id = id;
		datas.set(data->id, data);

		return data;
	}
	void giveback(int id) {
		playerdata_t* data = datas.get(id);
		datas.erase(id);
		free_datas.push_front(data);
		memset(data, -1, sizeof(*data));
	}
};

void player_dump(playerdata_t* player) {
	printf("---------\n");
	printf("id:%d\nname:%s\n", player->id, player->name[0]);
}

struct playerobj_t {
	playerdata_t* data;
	int id;

	void init(playerdata_t* data);
	void destroy();

	void att(int att, int value);
	int att(int att);
};


bool test_shm () {
	srand(time(NULL));
	my_clock_t g_clock;
	mapdatamgr_t mgr;

	assert(g_clock.init(1));
	assert(mgr.init());
	printf("free:%d used:%d\n", mgr.free_datas.size(), mgr.datas.size());


	for (int i=0; i<10; ++i) {
		g_clock.begin_update();

		for (int i=0; i<100; ++i) {
			playerdata_t* data = mgr.fetch(rand()%CACHED_NUM);
			assert(data);
			sprintf(data->name, "hello%d", data->id);
		}

		g_clock.end_update();
		g_clock.wait_frame();
		printf("free:%d used:%d\n", mgr.free_datas.size(), mgr.datas.size());
	}

	mgr.destroy();
	g_clock.destroy();

	return true;
}
